package com.msconfig.widget;

/*
 * author: caojunhao
 * date  : 2020/6/18
 * desc  :
 */

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.Scroller;

public class SlideView extends FrameLayout {
    private View contentView;
    private View menuView;
    private int contentWidth;
    private int menuWidth;
    private int viewHeight;
    private float startX;
    private float startY;
    private Scroller scroller;
    private String TAG="SlideView";

    public SlideView(@NonNull Context context) {
        this(context,null);
    }

    public SlideView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public SlideView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        scroller=new Scroller(context);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        contentView=getChildAt(0);
        menuView=getChildAt(1);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        contentWidth=contentView.getMeasuredWidth();
        menuWidth=menuView.getMeasuredWidth();
        viewHeight=getMeasuredHeight();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        menuView.layout(contentWidth,0,contentWidth+menuWidth,viewHeight);
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG, "onTouchEvent-ACTION_DOWN");
                //1.按下记录坐标
                startX = event.getX();
                startY = event.getY();
                if(onStateChangeListenter != null){
                    onStateChangeListenter.onDown(this);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "onTouchEvent-ACTION_MOVE");
                //2.记录结束坐标
                float endX = event.getX();
                float endY = event.getY();

                int distanceX = (int) (startX - endX);
                int oldScrollX = getScrollX();//先计算之前已经偏移了多少距离
                int toScrollX = (oldScrollX + distanceX);
                //getScrollX()、getScrollY()得到的是偏移量，是相对自己最刚开始位置的滑动偏移距离
                int toScrollY = getScrollY();
                //scrollTo是相反坐标（x左正y上正）
                //拦截边界值
                //当前是刚好的显示content，按理是不能向右滑动的，只能向左滑动的，scrollTo(-10,toScrollY)表示向右滑动
                if(toScrollX <0){
                    toScrollX =0;
                }
                if(toScrollX >menuWidth){
                    toScrollX =menuWidth;
                }
                scrollTo(toScrollX, toScrollY);

                //告诉listview要不要拦截--内部拦截法
                //在X轴和Y轴滑动的距离
                float DX = Math.abs(endX -startX);
                float DY = Math.abs(endY -startY);
                if(DX > DY&&DX>8){
                    //水平方向滑动
                    //响应侧滑
                    // 告诉listview不要拦截-事件给自身
                    getParent().requestDisallowInterceptTouchEvent(true);
                    Log.d(TAG, "onTouchEvent-ACTION_MOVE-requestDisallowInterceptTouchEvent");
                }
                startX = event.getX();
                startY = event.getY();
                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "onTouchEvent-ACTION_UP");
                //处理手指拿起之后的惯性事件，滑动距离大于等于menuWidth/2，打开menu菜单或者关闭
                int totalScrollX=getScrollX();
                if(totalScrollX>=menuWidth/2){
                    //打开Menu
                    openMenu();
                }else{
                    //打开Menu
                    closeMenu();
                }
                break;
        }
        return true;
    }

    public void closeMenu() {
        int distanceX = 0 - getScrollX();
        scroller.startScroll(getScrollX(), getScrollY(), distanceX, getScrollY());
        //2.在调用startScroll()的后面调用invalidate()；引起视图的重绘操作，从而触发ViewGroup中的computeScroll()被调用；
        invalidate();//强制刷新
        if(onStateChangeListenter != null){
            onStateChangeListenter.onClose(this);
        }
    }

    public void openMenu() {
        //1、通过Scroller类的startScroll()开始一个滑动动画控制，里面进行了一些轨迹参数的设置和计算
        //当前肯定是向左滑动的，因为打开menu，所以getScrollX()为正
        //注意：当前是先左滑动menu大于1/2的情况下，最大menuWidth，当前为getScrollX()。还要向左滑动menuWidth - getScrollX()
        int distanceX = menuWidth - getScrollX();
        scroller.startScroll(getScrollX(), getScrollY(), distanceX, getScrollY());
        //2.在调用startScroll()的后面调用invalidate()；引起视图的重绘操作，从而触发ViewGroup中的computeScroll()被调用；
        invalidate();//强制刷新
        if(onStateChangeListenter != null){
            onStateChangeListenter.onOpen(this);
        }
    }

    //3.在computeScroll()方法中，先调用Scroller类中的computeScrollOffset()方法，
    // 里面根据当前消耗时间进行轨迹坐标的计算，然后取得计算出的当前滑动的偏移坐标，调用
    // View的scrollTo()方法真正进行滑动控制，最后也需要调用invalidate()；进行重绘。
    @Override
    public void computeScroll() {
        super.computeScroll();
        if(scroller.computeScrollOffset()){
            //scroller.getCurrX()滑动偏移距离
            scrollTo(scroller.getCurrX(),scroller.getCurrY());
            invalidate();
        }
    }

    /**外部拦截法
     * true:拦截孩子的事件，但会执行当前控件的onTouchEvent()方法
     * false:不拦截孩子的事件，事件继续传递
     * @param event
     * @return
     */
    //要不要传递事件给子view
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercept = false;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG, "onInterceptTouchEvent-ACTION_DOWN");
                //1.按下记录坐标
                startX = event.getX();
                if(onStateChangeListenter != null){
                    onStateChangeListenter.onDown(this);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                Log.d(TAG, "onInterceptTouchEvent-ACTION_MOVE");
                //2.记录结束值
                float endX = event.getX();
                //在X轴和Y轴滑动的距离
                float DX = Math.abs(endX-startX);
                if(DX>8){
                    intercept = true;
                }
                startX = event.getX();
                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG, "onInterceptTouchEvent-ACTION_UP");
                break;
        }

        return intercept;
    }

    /**
     * 监听SlideLayout状态的改变
     */
    public interface OnStateChangeListenter{
        void onClose(SlideView view);
        void onDown(SlideView view);
        void onOpen(SlideView view);
    }

    private  OnStateChangeListenter onStateChangeListenter;

    /**
     * 设置SlideLayout状态的监听
     * @param onStateChangeListenter
     */
    public void setOnStateChangeListenter(OnStateChangeListenter onStateChangeListenter) {
        this.onStateChangeListenter = onStateChangeListenter;
    }

}
